package com.ruoyi.merchant.service.impl;

import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.merchant.domain.Merchant;
import com.ruoyi.merchant.domain.dto.*;
import com.ruoyi.merchant.domain.vo.MerchantInfoVO;
import com.ruoyi.merchant.mapper.MerchantMapper;
import com.ruoyi.merchant.service.IMerchantAuthService;
import com.ruoyi.merchant.utils.MerchantSecurityUtils;
import com.ruoyi.system.mapper.SysUserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Date;

/**
 * 商家认证Service实现
 */
@Service
@Slf4j
public class MerchantAuthServiceImpl implements IMerchantAuthService {

    @Autowired
    private MerchantMapper merchantMapper;

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private HttpServletRequest request;

    // 短信验证码缓存键前缀
    private static final String SMS_CODE_KEY = "sms_code:";


    /**
     * 商家注册
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult register(MerchantRegisterRequest request) {
        try {
            // 1. 检查手机号是否已注册（未删除的）
            Merchant existMerchant = merchantMapper.selectMerchantByPhone(request.getPhone());
            if (existMerchant != null) {
                return AjaxResult.error("该手机号已注册，请直接登录");
            }

            // 2. 检查sys_user是否存在（未删除的）
            SysUser existUser = userMapper.selectUserByUserName(request.getPhone());
            if (existUser != null) {
                return AjaxResult.error("该手机号已被使用");
            }

            // 3. 查询是否有已删除的记录（包含已删除的）
            SysUser deletedUser = userMapper.selectUserByUserNameIncludeDeleted(request.getPhone());

            Long userId;

            // 4. 处理sys_user
            if (deletedUser != null && "2".equals(deletedUser.getDelFlag())) {
                // 如果存在已删除的sys_user，先恢复它
                log.info("检测到已删除的sys_user记录，恢复它，userId: {}", deletedUser.getUserId());

                // 使用专门的恢复方法
                int rows = userMapper.restoreUser(deletedUser.getUserId());
                if (rows <= 0) {
                    throw new ServiceException("恢复系统用户失败");
                }

                // 然后更新密码等其他信息
                SysUser updateUser = new SysUser();
                updateUser.setUserId(deletedUser.getUserId());
                updateUser.setPassword(SecurityUtils.encryptPassword(request.getPassword()));
                updateUser.setNickName("商家_" + request.getPhone().substring(7));
                updateUser.setUpdateBy("merchant_reregister");
                updateUser.setUpdateTime(new Date());

                rows = userMapper.updateUser(updateUser);
                if (rows <= 0) {
                    throw new ServiceException("更新系统用户信息失败");
                }

                userId = deletedUser.getUserId();

                log.info("成功恢复sys_user，userId: {}", userId);
            } else if (deletedUser == null) {
                // 如果sys_user不存在，创建新的
                log.info("创建新的sys_user记录，phone: {}", request.getPhone());

                SysUser sysUser = new SysUser();
                sysUser.setUserName(request.getPhone());
                sysUser.setNickName("商家_" + request.getPhone().substring(7));
                sysUser.setPhonenumber(request.getPhone());
                sysUser.setPassword(SecurityUtils.encryptPassword(request.getPassword()));
                sysUser.setStatus("0");
                sysUser.setDelFlag("0");
                sysUser.setCreateBy("merchant_register");
                sysUser.setCreateTime(new Date());

                int rows = userMapper.insertUser(sysUser);
                if (rows <= 0) {
                    throw new ServiceException("创建用户失败");
                }
                userId = sysUser.getUserId();

                log.info("成功创建sys_user，userId: {}", userId);
            } else {
                // deletedUser存在但未删除，这种情况不应该发生
                throw new ServiceException("系统异常：用户状态不一致");
            }

            // 5. 创建商家记录
            Merchant merchant = new Merchant();
            merchant.setUserId(userId);
            merchant.setContactPhone(request.getPhone());
            merchant.setMerchantPassword(SecurityUtils.encryptPassword(request.getPassword()));
            merchant.setMerchantName("待完善");
            merchant.setContactPerson("待完善");
            merchant.setAddress("待完善");
            merchant.setLatitude(BigDecimal.ZERO);
            merchant.setLongitude(BigDecimal.ZERO);
            merchant.setBusinessLicense("待提交_" + System.currentTimeMillis());
            merchant.setFoodLicense("待提交_" + System.currentTimeMillis());
            merchant.setExternField1("PENDING_INFO");
            merchant.setStatus(1);
            merchant.setRating(BigDecimal.ZERO);

            int rows = merchantMapper.insertMerchant(merchant);
            if (rows <= 0) {
                throw new ServiceException("创建商家信息失败");
            }

            log.info("商家注册成功，merchantId: {}, userId: {}, phone: {}",
                    merchant.getMerchantId(), userId, request.getPhone());

            return AjaxResult.success("注册成功，请完善商家信息", merchant.getMerchantId());

        } catch (Exception e) {
            log.error("商家注册失败，phone: {}", request.getPhone(), e);
            throw new ServiceException("注册失败：" + e.getMessage());
        }
    }

    /**
     * 商家登录（仅验证商家信息）
     */
    @Override
    public AjaxResult login(MerchantLoginRequest request) {
        try {
            // 1. 查询商家信息
            Merchant merchant = merchantMapper.selectMerchantByPhone(request.getPhone());
            if (merchant == null) {
                return AjaxResult.error("账号不存在，请先注册");
            }

            // 2. 检查是否被删除
            if (merchant.getDeletedAt() != null) {
                return AjaxResult.error("账号已被注销");
            }

            // 3. 检查封禁状态
            if (merchant.getStatus() == 2) {
                return AjaxResult.error("账号已被封禁，请联系客服");
            }

            // 4. 密码登录方式需要验证密码
            if ("password".equals(request.getLoginType())) {
                if (!SecurityUtils.matchesPassword(
                        request.getPassword(), 
                        merchant.getMerchantPassword())) {
                    return AjaxResult.error("密码错误");
                }
            }
            // 短信登录在Controller已验证

            // 5. 构造商家信息
            MerchantInfoVO merchantInfo = buildMerchantInfo(merchant);

            log.info("商家登录验证通过，merchantId: {}, phone: {}", 
                     merchant.getMerchantId(), request.getPhone());

            return AjaxResult.success(merchantInfo);

        } catch (Exception e) {
            log.error("商家登录失败", e);
            return AjaxResult.error(e.getMessage());
        }
    }

    /**
     * 修改登录密码
     *
     * @param changePasswordDTO 密码修改信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int changePassword(ChangePasswordDTO changePasswordDTO) {
        // 从token中获取商家ID
        Long merchantId = MerchantSecurityUtils.getMerchantId();
        if (merchantId == null) {
            throw new ServiceException("未登录或登录已过期");
        }

        // 验证新密码和确认密码是否一致
        if (!changePasswordDTO.getNewPassword().equals(changePasswordDTO.getConfirmPassword())) {
            throw new ServiceException("两次输入的新密码不一致");
        }

        // 验证新密码不能与旧密码相同
        if (changePasswordDTO.getOldPassword().equals(changePasswordDTO.getNewPassword())) {
            throw new ServiceException("新密码不能与旧密码相同");
        }

        // 根据商家ID查询商家信息
        Merchant merchant = merchantMapper.selectMerchantById(merchantId);
        if (merchant == null) {
            throw new ServiceException("商家信息不存在");
        }

        // 检查是否关联了用户ID
        if (merchant.getUserId() == null) {
            throw new ServiceException("商家账户未关联系统用户，请联系管理员");
        }

        // 检查商家状态
        if (merchant.getStatus() == 2) {
            throw new ServiceException("商家已被封禁，无法修改密码");
        }

        // 验证旧密码是否正确
        if (StringUtils.isEmpty(merchant.getMerchantPassword())) {
            throw new ServiceException("商家密码未设置，请联系管理员");
        }

        if (!SecurityUtils.matchesPassword(changePasswordDTO.getOldPassword(), merchant.getMerchantPassword())) {
            throw new ServiceException("旧密码错误");
        }

        // 加密新密码
        String encryptedPassword = SecurityUtils.encryptPassword(changePasswordDTO.getNewPassword());

        // 1. 更新商家表密码
        int merchantRows = merchantMapper.updateMerchantPassword(merchantId, encryptedPassword);
        if (merchantRows <= 0) {
            throw new ServiceException("商家密码更新失败");
        }

        // 2. 更新系统用户表密码
        SysUser sysUser = new SysUser();
        sysUser.setUserId(merchant.getUserId());
        sysUser.setPassword(encryptedPassword);
        int userRows = sysUserMapper.updateUser(sysUser);
        if (userRows <= 0) {
            throw new ServiceException("系统用户密码更新失败");
        }

        return merchantRows;
    }

    /**
     * 忘记密码（通过手机验证码重置密码）
     *
     * @param forgotPasswordDTO 忘记密码信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int forgotPassword(ForgotPasswordDTO forgotPasswordDTO) {
        // 1. 验证新密码和确认密码是否一致
        if (!forgotPasswordDTO.getNewPassword().equals(forgotPasswordDTO.getConfirmPassword())) {
            throw new ServiceException("两次输入的新密码不一致");
        }

        // 2. 根据手机号查询商家信息
        Merchant merchant = merchantMapper.selectMerchantByPhone(forgotPasswordDTO.getPhone());
        if (merchant == null) {
            throw new ServiceException("该手机号未注册商家账户");
        }

        // 3. 检查商家状态
        if (merchant.getStatus() == 2) {
            throw new ServiceException("商家已被封禁，无法重置密码，请联系管理员");
        }

        // 4. 检查是否关联了用户ID
        if (merchant.getUserId() == null) {
            throw new ServiceException("商家账户未关联系统用户，请联系管理员");
        }

        // 5. 验证短信验证码（使用与登录接口相同的逻辑）
        String cacheKey = SMS_CODE_KEY + forgotPasswordDTO.getPhone();
        String cachedCode = redisCache.getCacheObject(cacheKey);

        if (StringUtils.isEmpty(cachedCode)) {
            throw new ServiceException("验证码已过期，请重新获取");
        }

        if (!cachedCode.equals(forgotPasswordDTO.getSmsCode())) {
            throw new ServiceException("验证码错误");
        }

        // 6. 加密新密码
        String encryptedPassword = SecurityUtils.encryptPassword(forgotPasswordDTO.getNewPassword());

        // 7. 更新商家表密码
        int merchantRows = merchantMapper.updateMerchantPassword(merchant.getMerchantId(), encryptedPassword);
        if (merchantRows <= 0) {
            throw new ServiceException("商家密码更新失败");
        }

        // 8. 更新系统用户表密码
        SysUser sysUser = new SysUser();
        sysUser.setUserId(merchant.getUserId());
        sysUser.setPassword(encryptedPassword);
        int userRows = sysUserMapper.updateUser(sysUser);
        if (userRows <= 0) {
            throw new ServiceException("系统用户密码更新失败");
        }

        // 9. 验证通过，删除缓存中的验证码
        redisCache.deleteObject(cacheKey);

        return merchantRows;
    }
    /**
     * 注销账号
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteAccount(DeleteAccountDTO deleteAccountDTO) {
        // 1. 从token中获取商家ID
        Long merchantId = MerchantSecurityUtils.getMerchantId();
        if (merchantId == null) {
            throw new ServiceException("未登录或登录已过期");
        }

        // 2. 根据商家ID查询商家信息
        Merchant merchant = merchantMapper.selectMerchantById(merchantId);
        if (merchant == null) {
            throw new ServiceException("商家信息不存在");
        }

        // 3. 检查商家是否已删除
        if (merchant.getDeletedAt() != null) {
            throw new ServiceException("商家账号已注销");
        }

        // 4. 验证密码
        if (StringUtils.isEmpty(merchant.getMerchantPassword())) {
            throw new ServiceException("商家密码未设置，请联系管理员");
        }

        if (!SecurityUtils.matchesPassword(deleteAccountDTO.getPassword(), merchant.getMerchantPassword())) {
            throw new ServiceException("密码错误，无法注销账号");
        }

        // 5. 软删除商家账号
        int merchantRows = merchantMapper.softDeleteMerchant(merchantId);
        if (merchantRows <= 0) {
            throw new ServiceException("商家账号注销失败");
        }

        // 6. 如果关联了系统用户，使用 RuoYi 的删除方法
        if (merchant.getUserId() != null) {
            // 使用 RuoYi 框架提供的删除方法
            int userRows = userMapper.deleteUserById(merchant.getUserId());
            if (userRows <= 0) {
                throw new ServiceException("系统用户删除失败");
            }

            log.info("成功软删除sys_user，userId: {}", merchant.getUserId());
        }

        // 7. 记录注销原因
        if (StringUtils.isNotEmpty(deleteAccountDTO.getReason())) {
            log.info("商家注销，merchantId: {}, userId: {}, reason: {}",
                    merchantId, merchant.getUserId(), deleteAccountDTO.getReason());
        }

        // 8. 清除登录token
        LoginUser loginUser = tokenService.getLoginUser(request);
        if (loginUser != null && StringUtils.isNotEmpty(loginUser.getToken())) {
            tokenService.delLoginUser(loginUser.getToken());
        }

        return merchantRows;
    }


    @Override
    public boolean logout() {
        try {
            // 1. 获取当前登录用户信息
            LoginUser loginUser = tokenService.getLoginUser(request);
            if (loginUser == null) {
                return true; // 已经退出或未登录
            }

            // 2. 删除Redis中的token
            if (StringUtils.isNotEmpty(loginUser.getToken())) {
                tokenService.delLoginUser(loginUser.getToken());
            }
            return true;
        } catch (Exception e) {
            throw new ServiceException("退出登录失败：" + e.getMessage());
        }
    }


    /**
     * 构造商家信息VO
     */
    private MerchantInfoVO buildMerchantInfo(Merchant merchant) {
        //1.获取审核状态
        String auditStatus = StringUtils.defaultIfBlank(
                merchant.getExternField1(), "PENDING_INFO");
        // 2. 修正：基于审核状态判断信息是否完善
        // - PENDING_INFO: 待完善（未提交过申请）
        // - UNDER_REVIEW: 审核中（已提交申请，信息已完善）
        // - APPROVED: 审核通过（信息完善）
        // - REJECTED: 审核驳回（信息完善但被拒绝）
        boolean isInfoComplete = !"PENDING_INFO".equals(auditStatus);
        // 3. 判断是否可以营业
        // - 必须审核通过（APPROVED）
        // - 且商家状态为营业中（0）
        boolean canOperate = "APPROVED".equals(auditStatus)
                && merchant.getStatus() != null
                && merchant.getStatus() == 0;
        //4.构建返回对象
        return MerchantInfoVO.builder()
                .merchantId(merchant.getMerchantId())
                .merchantName(merchant.getMerchantName())
                .contactPhone(desensitizePhone(merchant.getContactPhone()))
                .avatarUrl(merchant.getAvatarUrl())
                .status(merchant.getStatus())
                .auditStatus(auditStatus)
                .isInfoComplete(isInfoComplete)
                .canOperate(canOperate)
                .build();
    }

    /**
     * 手机号脱敏
     */
    private String desensitizePhone(String phone) {
        if (StringUtils.isEmpty(phone) || phone.length() != 11) {
            return phone;
        }
        return phone.substring(0, 3) + "****" + phone.substring(7);
    }
}
